/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.security;

import org.apache.catalina.startup.CatalinaProperties;

import java.security.Security;

/**
 * Util class to protect Catalina against package access and insertion.
 * The code are been moved from Catalina.java
 *
 * @author the Catalina.java authors
 * @author Jean-Francois Arcand
 */
public final class SecurityConfig {
	private static final org.apache.juli.logging.Log log =
			org.apache.juli.logging.LogFactory.getLog(SecurityConfig.class);
	private static final String PACKAGE_ACCESS = "sun.,"
			+ "org.apache.catalina."
			+ ",org.apache.jasper."
			+ ",org.apache.coyote."
			+ ",org.apache.tomcat.";
	// FIX ME package "javax." was removed to prevent HotSpot
	// fatal internal errors
	private static final String PACKAGE_DEFINITION = "java.,sun."
			+ ",org.apache.catalina."
			+ ",org.apache.coyote."
			+ ",org.apache.tomcat."
			+ ",org.apache.jasper.";
	private static SecurityConfig singleton = null;
	/**
	 * List of protected package from conf/catalina.properties
	 */
	private String packageDefinition;

	/**
	 * List of protected package from conf/catalina.properties
	 */
	private String packageAccess;

	/**
	 * Create a single instance of this class.
	 */
	private SecurityConfig() {
		try {
			packageDefinition = CatalinaProperties.getProperty("package.definition");
			packageAccess = CatalinaProperties.getProperty("package.access");
		} catch (java.lang.Exception ex) {
			if (log.isDebugEnabled()) {
				log.debug("Unable to load properties using CatalinaProperties", ex);
			}
		}
	}

	/**
	 * Returns the singleton instance of that class.
	 *
	 * @return an instance of that class.
	 */
	public static SecurityConfig newInstance() {
		if (singleton == null) {
			singleton = new SecurityConfig();
		}
		return singleton;
	}

	/**
	 * Set the security package.access value.
	 */
	public void setPackageAccess() {
		// If catalina.properties is missing, protect all by default.
		if (packageAccess == null) {
			setSecurityProperty("package.access", PACKAGE_ACCESS);
		} else {
			setSecurityProperty("package.access", packageAccess);
		}
	}

	/**
	 * Set the security package.definition value.
	 */
	public void setPackageDefinition() {
		// If catalina.properties is missing, protect all by default.
		if (packageDefinition == null) {
			setSecurityProperty("package.definition", PACKAGE_DEFINITION);
		} else {
			setSecurityProperty("package.definition", packageDefinition);
		}
	}

	/**
	 * Set the proper security property
	 *
	 * @param properties the package.* property.
	 */
	private final void setSecurityProperty(String properties, String packageList) {
		if (System.getSecurityManager() != null) {
			String definition = Security.getProperty(properties);
			if (definition != null && definition.length() > 0) {
				if (packageList.length() > 0) {
					definition = definition + ',' + packageList;
				}
			} else {
				definition = packageList;
			}

			Security.setProperty(properties, definition);
		}
	}


}


